/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package dbproxy;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import util.Peticion;
import util.PeticionDeserializer;
import util.PojosFactory;
import util.Query;
import util.Respuesta;
import util.RespuestaDeserializer;

/**
 * <p>Esta es la clase que se encarga de escuchar la peticion del cliente y
 * enviarle una respuesta.</p>
 * <p>Una peticion tiene un tipo, y luego puede contener o bien un objeto Query,
 * o un array de pojos. </p>
 *
 * @see Peticion
 * @see Respuesta
 * @see util.Query
 * @author Miguel
 */
public class DBProxy implements Runnable {

    private Socket sck;
    private LogInterface log;

    public DBProxy(Socket sck, LogInterface log) {
        this.sck = sck;
        this.log = log;
    }

    @Override
    public void run() {
        BufferedReader br = null;
        PrintWriter pw = null;
        Connection con = null;
        List<Respuesta> resps = new ArrayList<>();
        Gson gs = new GsonBuilder()
                .setDateFormat(PojosFactory.getSdf().toPattern())
                .registerTypeAdapter(Peticion.class, new PeticionDeserializer())
                .registerTypeAdapter(Respuesta.class, new RespuestaDeserializer())
                .create();
        try {
            Class.forName("com.mysql.jdbc.Driver");
            con = DriverManager.getConnection("jdbc:mysql://localhost/"
                    + "digitalify_db", "root", "");
            pw = new PrintWriter(new OutputStreamWriter(sck.getOutputStream(), "UTF-8"), true);            
            System.out.println("Se abrió la conexion con la BD");
            log.recibirLinea("Se abrió la conexion con la BD");
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(DBProxy.class.getName()).log(Level.SEVERE, null, ex);
            Respuesta resp = new Respuesta(-1, "Error: " + ex.getMessage());
            resps.add(resp);
        } catch (SQLException ex) {
            Respuesta resp = new Respuesta(-1, "Error: " + ex.getMessage());
            resps.add(resp);
            Logger.getLogger(DBProxy.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(DBProxy.class.getName()).log(Level.SEVERE, null, ex);
        }
        if (con != null) {
            try {

                br = new BufferedReader(new InputStreamReader(sck.getInputStream()));

                //Escuchar la peticion del cliente
                String linea = br.readLine();
                System.out.println("se recibio: " + linea);
                log.recibirLinea("se recibio: " + linea);
                while (!linea.isEmpty()) {
                    Peticion peticion = null;
                    peticion = gs.fromJson(linea, Peticion.class);
                    switch (peticion.getTipo()) {
                        case Peticion.TIPO_SELECT:
                            //Ejecutar Select
                            resps.add(peticion.ejecutarQuery(con));
                            break;
                        case Peticion.TIPO_MODIFICAR:
                            //Reflejar los cambios en los pojos a la BD
                            resps.add(peticion.guardarPojos(con));
                            break;
                        case Peticion.TIPO_BORRAR:
                            resps.add(peticion.borrarPojos(con));
                            break;
                    }
                    linea = br.readLine();
                }
                if (pw != null) {
                    for (Respuesta resp : resps) {
                        pw.println(gs.toJson(resp));
                    }
                    pw.println();
                }


            } catch (IOException ex) {
                Logger.getLogger(DBProxy.class.getName()).log(Level.SEVERE, null, ex);
            } catch (SQLException ex) {
                Logger.getLogger(DBProxy.class.getName()).log(Level.SEVERE, null, ex);
            } catch (ParseException ex) {
                Logger.getLogger(DBProxy.class.getName()).log(Level.SEVERE, null, ex);
            } finally {
                try {
                    if (br != null) {
                        br.close();
                    }
                    if (pw != null) {
                        pw.close();
                    }
                    con.close();
                } catch (IOException ex) {
                    Logger.getLogger(DBProxy.class.getName()).log(Level.SEVERE, null, ex);
                } catch (SQLException ex) {
                    Logger.getLogger(DBProxy.class.getName()).log(Level.SEVERE, null, ex);
                }
            }

        } else if (pw != null) {

            pw.println(gs.toJson(new Respuesta(-1, "No se pudo establecer "
                    + "la conexion con la BD")));
            pw.println();
        }

    }
    //Reconstruir la peticion en caso que contenga pojos     

//    private Peticion obtenerPeticion(JsonObject jsobj, Gson gs) {
//        JsonArray jsarr = jsobj.get("pojos").getAsJsonArray();
//        int tipo_pojos = jsobj.get("tipo_pojos").getAsInt();
//        Pojo[] pojos = null;
//        switch (tipo_pojos) {
//            case Query.USUARIO_ARRAY:
//                pojos = gs.fromJson(jsarr, Usuario[].class);
//                break;
//            case Query.PRODUCTO_ARRAY:
//                pojos = gs.fromJson(jsarr, Producto[].class);
//                break;
//            case Query.DESCARGA_ARRAY:
//                pojos = gs.fromJson(jsarr, Descargas[].class);
//                break;
//            case Query.MOVIMIENTO_ARRAY:
//                pojos = gs.fromJson(jsarr, Movimientos[].class);
//                break;
//            case Query.PEDIDO_ARRAY:
//                pojos = gs.fromJson(jsarr, Pedido[].class);
//                break;
//            case Query.PRODUCTOCATEGORIA_ARRAY:
//                pojos = gs.fromJson(jsarr, ProductoCategoria[].class);
//                break;
//
//        }
//
//        return new Peticion(jsobj.get("tipo").getAsInt(), tipo_pojos, pojos);
//    }
}
